"""
用户认证路由
"""
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from pydantic import BaseModel, EmailStr

from database import get_db, get_db_for_refresh
from auth import AuthHandler, create_refresh_token_record, revoke_refresh_token, cleanup_expired_tokens
from models import User, LoginLog, Wallet, RefreshToken
from schemas import Token, LoginRequest, RegisterRequest, RefreshTokenRequest, BaseResponse, UserResponse, AuthResponse

router = APIRouter()

@router.post("/login")
async def login(
    login_data: dict,
    db: Session = Depends(get_db)
):
    """用户登录"""
    try:
        print(f"收到登录请求: {login_data}")
        
        # 获取用户名和密码
        username = login_data.get('username')
        password = login_data.get('password')
        
        if not username or not password:
            print("用户名或密码为空")
            return {"error": "用户名和密码为必填项"}
        
        print(f"用户名: {username}")
        
        # 查询用户
        user = db.query(User).filter(
            (User.username == username) | (User.email == username)
        ).first()
        
        if not user:
            print("用户不存在")
            return {"error": "用户不存在"}
        
        print(f"找到用户: {user.username}, 状态: {user.status}")
        
        # 验证密码
        if not AuthHandler.verify_password(password, user.password_hash):
            print("密码错误")
            return {"error": "用户名或密码错误"}
        
        if user.status != 'active':
            print("账户状态异常")
            return {"error": "账户已被禁用或删除"}
        
        print("用户认证成功")
        
        # 创建令牌
        access_token_expires = timedelta(minutes=60)
        access_token = AuthHandler.create_access_token(
            data={"sub": user.username}, expires_delta=access_token_expires
        )
        
        refresh_token_expires = timedelta(days=7)
        refresh_token = AuthHandler.create_refresh_token(
            data={"sub": user.username}, expires_delta=refresh_token_expires
        )
        
        print("令牌创建成功")
        
        # 保存刷新令牌
        create_refresh_token_record(
            db, user.id, refresh_token,
            datetime.utcnow() + refresh_token_expires
        )
        db.commit()
        
        print("刷新令牌保存成功")
        
        return {
            "access_token": access_token,
            "expires_in": 3600,
            "refresh_token": refresh_token
        }
        
    except Exception as e:
        print(f"登录过程中发生错误: {e}")
        import traceback
        traceback.print_exc()
        return {"error": f"服务器内部错误: {str(e)}"}

@router.post("/register", response_model=AuthResponse)
async def register(
    register_data: dict,  # 改为接收原始字典数据
    db: Session = Depends(get_db)
):
    """用户注册"""
    # 验证必需字段
    if not register_data.get('username') or not register_data.get('email') or not register_data.get('password'):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="用户名、邮箱和密码为必填项"
        )
    
    # 移除confirmPassword字段，只保留需要的字段
    filtered_data = {
        'username': register_data.get('username'),
        'email': register_data.get('email'), 
        'password': register_data.get('password')
    }
    
    # 检查用户名是否已存在
    existing_user = db.query(User).filter(
        (User.username == filtered_data['username']) | (User.email == filtered_data['email'])
    ).first()
    
    if existing_user:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="用户名或邮箱已存在"
        )
    
    # 创建新用户
    hashed_password = AuthHandler.get_password_hash(filtered_data['password'])
    user = User(
        username=filtered_data['username'],
        nickname=filtered_data['username'],  # 使用用户名作为昵称
        email=filtered_data['email'],
        password_hash=hashed_password,
        avatar_url=None,  # 设置为None，因为前端没有发送头像URL
        status='active'
    )
    
    try:
        db.add(user)
        db.commit()
        db.refresh(user)
        print(f"用户创建成功: {user.id}")
        
        # 创建用户钱包
        wallet = Wallet(user_id=user.id, balance=0.00)
        db.add(wallet)
        db.commit()
        print(f"钱包创建成功: {wallet.id}")
        
    except Exception as e:
        print(f"数据库操作失败: {e}")
        print(f"异常类型: {type(e)}")
        print(f"异常详情: {str(e)}")
        import traceback
        traceback.print_exc()
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"数据库操作失败: {str(e)}"
        )
    
    # 创建访问令牌
    access_token_expires = timedelta(minutes=60)  # 1小时
    access_token = AuthHandler.create_access_token(
        data={"sub": user.username}, expires_delta=access_token_expires
    )
    
    # 创建刷新令牌
    refresh_token_expires = timedelta(days=7)  # 7天
    refresh_token = AuthHandler.create_refresh_token(
        data={"sub": user.username}, expires_delta=refresh_token_expires
    )
    
    # 保存刷新令牌
    create_refresh_token_record(
        db, user.id, refresh_token, 
        datetime.utcnow() + refresh_token_expires
    )
    
    # 返回前端期望的格式 - 统一返回扁平结构，与login接口保持一致
    return AuthResponse(
        message="注册成功",
        data={
            "user": {
                "id": user.id,
                "username": user.username,
                "nickname": user.nickname,
                "email": user.email,
                "avatar_url": user.avatar_url,
                "is_verified": user.is_verified,
                "status": user.status,
                "balance": user.balance,
                "created_at": user.created_at
            },
            "access_token": access_token,
            "refresh_token": refresh_token
        }
    )

@router.post("/refresh", response_model=Token)
async def refresh_token(
    refresh_data: RefreshTokenRequest,
    db: Session = Depends(get_db)
):
    """刷新访问令牌 - 详细调试版本"""
    print("=== refresh端点开始执行 ===")
    print(f"请求数据: {refresh_data}")
    print(f"Refresh Token: {refresh_data.refresh_token[:50]}...")
    
    try:
        print(f"1. 验证刷新令牌")
        # 验证刷新令牌
        payload = AuthHandler.verify_token(refresh_data.refresh_token)
        username: str = payload.get("sub")
        token_type: str = payload.get("type")
        token_exp: int = payload.get("exp")
        
        print(f"   令牌解析结果: 用户名={username}, 类型={token_type}, 过期时间={token_exp}")
        print(f"   令牌验证: exp={token_exp}, current_time={datetime.utcnow().timestamp()}")
        
        if username is None or token_type != "refresh":
            print(f"   ❌ 令牌验证失败: username={username}, token_type={token_type}")
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效的刷新令牌"
            )
        
        print(f"   ✅ 令牌验证成功")
        
        print(f"2. 检查数据库中的令牌记录")
        # 检查令牌是否被撤销
        refresh_token_record = db.query(RefreshToken).filter(
            RefreshToken.token == refresh_data.refresh_token,
            RefreshToken.is_revoked == False
        ).first()
        
        if not refresh_token_record:
            print(f"   ❌ 数据库中未找到有效的refresh token记录")
            print(f"   查找条件: token={refresh_data.refresh_token[:50]}..., is_revoked=False")
            
            # 检查所有refresh token记录
            all_tokens = db.query(RefreshToken).all()
            print(f"   数据库中总共有 {len(all_tokens)} 个refresh token记录")
            for token in all_tokens[-5:]:  # 显示最近5个记录
                print(f"      Token: {token.token[:50]}..., is_revoked: {token.is_revoked}")
            
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="令牌已失效"
            )
        
        print(f"   ✅ 找到refresh token记录，用户ID: {refresh_token_record.user_id}")
        
        print(f"3. 获取用户信息")
        # 获取用户
        user = db.query(User).filter(User.username == username).first()
        if not user:
            print(f"   ❌ 未找到用户: {username}")
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="用户不存在"
            )
        
        print(f"   ✅ 找到用户: {user.id}, {user.username}")
        
        print(f"4. 创建新令牌")
        # 创建新的访问令牌
        access_token_expires = timedelta(minutes=60)
        access_token = AuthHandler.create_access_token(
            data={"sub": user.username}, expires_delta=access_token_expires
        )
        
        # 创建新的刷新令牌
        refresh_token_expires = timedelta(days=7)
        new_refresh_token = AuthHandler.create_refresh_token(
            data={"sub": user.username}, expires_delta=refresh_token_expires
        )
        
        print(f"   ✅ 令牌创建成功")
        
        print(f"5. 执行数据库操作")
        try:
            # 撤销旧令牌，保存新令牌
            revoke_refresh_token(db, refresh_data.refresh_token)
            create_refresh_token_record(
                db, user.id, new_refresh_token,
                datetime.utcnow() + refresh_token_expires
            )
            db.commit()  # 手动提交事务
            print(f"   ✅ 数据库操作成功")
        except Exception as db_error:
            db.rollback()  # 数据库操作失败时回滚
            print(f"   ❌ 数据库操作失败: {db_error}")
            import traceback
            traceback.print_exc()
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"数据库操作失败: {str(db_error)}"
            )
        
        print(f"=== refresh端点执行成功 ===")
        return Token(
            access_token=access_token,
            expires_in=3600,
            refresh_token=new_refresh_token
        )
        
    except HTTPException as e:
        print(f"=== HTTPException: {e.detail} ===")
        raise
    except Exception as e:
        print(f"=== refresh端点异常: {e} ===")
        import traceback
        traceback.print_exc()
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="令牌刷新失败"
        )

@router.post("/logout", response_model=BaseResponse)
async def logout(
    refresh_data: RefreshTokenRequest,
    db: Session = Depends(get_db)
):
    """用户登出"""
    revoke_refresh_token(db, refresh_data.refresh_token)
    return BaseResponse(message="登出成功")

class ForgotPasswordRequest(BaseModel):
    """忘记密码请求模型"""
    email: EmailStr

class ResetPasswordRequest(BaseModel):
    """重置密码请求模型"""
    token: str
    new_password: str

@router.post("/cleanup-tokens", response_model=BaseResponse)
async def cleanup_tokens(db: Session = Depends(get_db)):
    """清理过期令牌（管理员功能）"""
    cleanup_expired_tokens(db)
    return BaseResponse(message="令牌清理完成")

@router.post("/forgot-password", response_model=BaseResponse)
async def forgot_password(
    request: ForgotPasswordRequest,
    db: Session = Depends(get_db)
):
    """请求重置密码"""
    # 检查用户是否存在
    user = db.query(User).filter(User.email == request.email).first()
    if not user:
        # 为了安全，即使邮箱不存在也返回成功消息
        return BaseResponse(message="如果邮箱存在，重置密码链接将发送到该邮箱")
    
    # 创建密码重置令牌
    reset_token = AuthHandler.create_access_token(
        data={"sub": user.username}, 
        expires_delta=timedelta(hours=1)  # 1小时内有效
    )
    
    # 这里应该添加发送邮件的逻辑
    # 例如：send_reset_email(user.email, reset_token)
    
    return BaseResponse(message="如果邮箱存在，重置密码链接将发送到该邮箱")

@router.post("/reset-password", response_model=BaseResponse)
async def reset_password(
    request: ResetPasswordRequest,
    db: Session = Depends(get_db)
):
    """重置密码"""
    try:
        # 验证重置令牌
        payload = AuthHandler.verify_token(request.reset_token)
        username: str = payload.get("sub")
        if username is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="无效的重置令牌"
            )
        
        # 查找用户
        user = db.query(User).filter(User.username == username).first()
        if not user:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="用户不存在"
            )
        
        # 更新密码
        user.password_hash = AuthHandler.get_password_hash(request.new_password)
        db.commit()
        
        return BaseResponse(message="密码重置成功")
    except JWTError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效或过期的重置令牌"
        )